package net

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/MyProj/PrjHttpWs"
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/supervalue"
)

/**
  通过WsClient连接到服务器接收命令处理
*/

type ProjWsCmdCltPlug struct {
	conf   *wrapper.SuperValue
	plugId string
	topic  string

	wsclt        *PrjHttpWs.WsHttpClt
	monitor_send *utils.MonitorSpeedSizeRec
	monitor_recv *utils.MonitorSpeedSizeRec
}

func (this *ProjWsCmdCltPlug) procJson(sender *PrjHttpWs.WsHttpClt, json *wrapper.SuperValue) {
	respTopic := json.StringByName("resp-topic", "")
	cmd := json.ValueByName("list")
	if cmd == nil {
		cmd = json
		cmd.RemoveKey("resp-topic")
	}

	n := 0
	cmd.Range(func(key string, val *wrapper.SuperValue) bool {
		_, errcode, err := PlgOnPlugRecvCmd(val)
		if err != nil {
			if len(respTopic) > 0 {
				e1 := this.SendKVs(respTopic, "errcode", errcode, "msg", err.Error())
				if e1 != nil {
					utils.Log.WarnTypef(this.plugId, "响应异常:%s", e1.Error())
				}
			} else {
				utils.Log.WarnTypef(this.plugId, "处理命令异常:%s", err.Error())
			}
		} else {
			n++
			utils.Log.DebugTypef(this.plugId, "插件[%s], 数据:%s", val.StringByName("id", ""), val.AsJSONString(false))
		}
		return true
	})

}

/*
*

	{
	   "list":[
	      {}
	   ],
	   "resp-topic":"/响应主题"
	}
*/
func (this *ProjWsCmdCltPlug) OnHttpWsRecvTopic(sender *PrjHttpWs.WsHttpClt, topic string, data interface{}) {
	utils.Log.DebugTypef(this.plugId, "接收到[%s]命令:%v", topic, data)
	if json, ok := data.(*wrapper.SuperValue); ok {
		this.procJson(sender, json)
	} else if str, ok := data.(string); ok {
		json, err := wrapper.NewSVFromBuf([]byte(str))
		if err != nil {
			utils.Log.WarnTypef(this.plugId, "收到非法的命令数据, 非法的JSON格式")
		} else {
			this.procJson(sender, json)
		}
	} else {
		utils.Log.WarnTypef(this.plugId, "收到非法的命令数据")
	}
	return
}

func (this *ProjWsCmdCltPlug) SendKVs(topic string, kv ...interface{}) error {
	if this.wsclt != nil {
		l := len(kv)
		if l == 1 {
			return this.wsclt.PublishMessage(topic, kv[0])
		}
		json := wrapper.NewSVObject()
		json.SetKeyValues(kv...)
		return this.wsclt.PublishMessage(topic, json)
	} else {
		return fmt.Errorf("WS连接尚未进行创建")
	}
}

/*
**

	{
	   "url":"ws://xxxxx:xx",
	   "topic":"/cmd/$appuuid$"
	}
*/
func (this *ProjWsCmdCltPlug) ReloadConf(conf *wrapper.SuperValue) error {

	if this.monitor_send == nil {
		this.monitor_send = utils.NewMonitorSpeedSizeRec()
		this.monitor_recv = utils.NewMonitorSpeedSizeRec()
		utils.Monitor.AddMonitorRec(this.monitor_send, this.monitor_send)
		utils.Monitor.AddMonitorRec(this.monitor_recv, this.monitor_recv)
	}

	wsurl := conf.StringByPath("url", "")
	topic := conf.StringByName("topic", "")
	if len(topic) > 0 {
		topic = ReplacePlaceholderForFileName(topic)
	}

	if len(wsurl) > 0 && (this.conf == nil || wsurl != this.conf.StringByPath("url", "")) {
		if this.wsclt != nil {
			utils.GoFunc2(this.wsclt.Stop)
			this.wsclt = nil
		}
		wsclt := PrjHttpWs.NewWsHttpClt(wsurl, "")
		wsclt.LogTypeStr = this.plugId
		wsclt.ConfigOnRecvTopic(this.OnHttpWsRecvTopic)
		wsclt.ConfigMonitor(this.monitor_send, this.monitor_recv)
		utils.GoFunc2(wsclt.Start)
		if len(topic) > 0 {
			this.topic = topic
		}
		wsclt.SubScribleTopic(this.topic)
		this.wsclt = wsclt
	} else {
		if this.wsclt == nil {
			return fmt.Errorf("请先指定URL进行创建WS连接")
		}

		if len(topic) > 0 && this.topic != topic {
			this.topic = topic
			this.wsclt.SubScribleTopic(this.topic)
		}

		if len(this.topic) == 0 {
			return fmt.Errorf("请指定要订阅的主题")
		}
	}
	this.conf = conf.Clone()
	return nil
}

func (this *ProjWsCmdCltPlug) OnHttpStatus(rec *PlgHttpRec) (rval interface{}, errcode int, err error) {
	json := wrapper.NewSVObject()
	json.SetKeyValues("send-size", this.monitor_send.SizeInfo(), "recv-size", this.monitor_recv.SizeInfo(),
		"conn-n", this.wsclt.GetConnNum(),
		"connected", this.wsclt != nil && this.wsclt.IsConnected(), "lastdis", this.wsclt.LastDisreason())
	PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.AsJSONString(false))
	return
}

func (this *ProjWsCmdCltPlug) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		} else {
			err = fmt.Errorf("非法的JSON配置")
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {
		if this.wsclt != nil {
			utils.GoFunc2(this.wsclt.Stop)
			this.wsclt = nil
		}
	}
	return
}

func CreateProjWsCmdCltPlugFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ProjWsCmdCltPlug{}
	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.plugId = str
		}
	}
	rval = obj
	return
}
